
//
// 110520 - AH - (Special) Created.
// 110521 - AH - Fixed so first and second level can not be duplicates.
// 120218 - AH - (Jackob's) Tuple levels replaced last level.
// 120224 - AH - (Baran) Gets not Lines but the ConversationElement.
//

package org.soekrat.engine.visitor;

import java.io.CharArrayWriter;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;

import org.soekrat.engine.motor.ConversationElement;

/**
 * <p>
 *   Split input from visitor into
 *   {@link Input} at different levels. 
 * </p>
 * @author Arne Halvorsen (AH)
 * @author Laetitia Le Chatton (LLC) 
 */
public final class SplitScale implements Iterable<Input>
{
  private List<Input> m_splits=new ArrayList<Input>();
  
  /**
   * <p>
   *   Constructor.
   * </p>
   * @param lines {@link Lines} to create from.
   */
  public SplitScale(ConversationElement ce)
  {
    if (ce==null)
    {
      throw new NullPointerException("ce");
    }
    
    Lines lines=(Lines)ce.getAttribute(ConversationElement.LINES);
    
    // Level 0, highest level.
    Input l0=new Input();
    for (Line curr : lines)
    {
      l0.add(curr.getText());
    }
    m_splits.add(l0);
    
    if (sentenceSeparation(lines))
    {
      // Level 1
      Input l1=new Input();
      for (Line curr : lines)
      {
        StringTokenizer st=new StringTokenizer(curr.getText(), ",");
        while (st.hasMoreTokens())
        {
          String t=st.nextToken();
          t=t.trim();
          l1.add(t);
        }
      }
      m_splits.add(l1);
    }
    
    Input all=lines.getInput();
    
    int n=all.size();
    if (n>1)
    {
      int nm1=n-1;
      for (int i=nm1; i>=1; i--) 
      {
        Input level=new Input();
        TupleFactory.createTuples(all, level, i);
        m_splits.add(level);
      }
    }
    
    /*
    // Level 2,
    Input l2=new Input();
    for (Line curr : lines)
    {
      Input tokens=curr.getInput();
      
      l2.add(tokens);
    }
    m_splits.add(l2);
    */
  }
  
  /*
  private void removeDuplicateLevels()
  {
    int n=m_splits.size();
    for (int i=0; i>0; i--)
    {
      Input over=m_splits.get(i);
      Input under=m_splits.get(i-1);
      if (over.equals(under)) m_splits.remove(i);
    }
  }
  */
  
  private boolean sentenceSeparation(Lines lines)
  {
    for (Line line : lines) 
    {
      if (line.contains(',')) return true;  
    }
    return false;
  }
  
  /**
   * <p>
   *   Gets number of levels.
   * </p>
   * @return Count.
   */
  public int getLevelCount(){ return m_splits.size(); }
  
  /**
   * <p>
   *   Gets first level.
   * </p>
   * @return {@link Input} that is first level.
   */
  public Input getFirstLevel(){ return m_splits.get(0); }
  
  /**
   * <p>
   *   Gets level.
   * </p>
   * @param idx Index of level to get.
   * @return {@link Input} that is the level.
   * @throws IndexOutOfBoundsException If {@code idx<0 || idx>=getLevelCount()}.
   */
  public Input getLevel(int idx){ return m_splits.get(idx); }
  
  /**
   * <p>
   *   Gets last level.
   * </p>
   * @return {@link Input} that is last level.
   */
  public Input getLastLevel(){ return m_splits.get(m_splits.size()-1); }
  
  @Override
  public String toString() 
  {
    CharArrayWriter caw=new CharArrayWriter();
    PrintWriter pw=new PrintWriter(caw);
    
    StringBuilder sb=new StringBuilder();
    
    int n=m_splits.size();
    for (int i=0; i<n; i++)
    {
      Input input=m_splits.get(i);
      sb.append("level=").append(i).append(", input=").append(input);
      pw.println(sb);
      sb.setLength(0);
    }
    
    pw.flush();
    return caw.toString();
  }
  
  @Override
  public Iterator<Input> iterator(){ return m_splits.iterator(); }
  
}
